using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Collections.Specialized;
using System.Collections;

namespace ru.yourpictures.Core.Imaging.Filters.PhotoFilters
{
    /// <summary>
    /// Resize filter class. A simple functionality to resize images
    /// Reference: http://www.codeproject.com/KB/cs/yael_image_filters.aspx
    /// </summary>
    [FilterImplementation(GdiPlusImplemented = true, LowLevelImplemented = false)]
    public class Resize : FilterBase 
    {
        #region Private Fields
        private int _newWidth = 50;
        private int _newHeight = 50;
        private float _aspectRatio;
        private bool _keepAspectRatio = false;
        private bool _lockRatioByHeight = false;
        private bool _lockRatioByWidth = true;
        #endregion Private Fields

        #region Filter Properties
        /// <summary>
        /// Image width in pixels
        /// </summary>
        public int Width
        {
            set
            {
                _newWidth = value;
                _lockRatioByWidth = true;
                _lockRatioByHeight = false;
            }
            get{ return _newWidth; }
        }
        /// <summary>
        /// Image height in pixels
        /// </summary>
        public int Height
        {
            set
            {
                _newHeight = value;
                _lockRatioByWidth = false;
                _lockRatioByHeight = true;
            }
            get { return _newHeight; }
        }
        /// <summary>
        /// Determines whether to keep the original aspect ratio
        /// false by default. Should be turned on before setting the width or height to 
        /// keep the original ratio
        /// </summary>
        public bool KeepAspectRatio
        {
            get { return _keepAspectRatio; }
            set { _keepAspectRatio = value; }
        }

        /// <summary>
        /// Locks the aspect ratio while keeping the height as reference.
        /// Meaning that setting a new height will calc the width according to the original ratio
        /// </summary>
        public bool LockRatioByHeight
        {
            get { return _lockRatioByHeight; }
            set
            {
                _lockRatioByHeight = value;
                _keepAspectRatio = true;
                _lockRatioByWidth = !_lockRatioByHeight;
            }
        }

        /// <summary>
        /// Locks the aspect ratio while keeping the width as reference.
        /// Meaning that setting a new width will calc the height according to the original ratio
        /// </summary>
        public bool LockRatioByWidth
        {
            get { return _lockRatioByWidth; }
            set
            {
                _lockRatioByWidth = value;
                _keepAspectRatio = true;
                _lockRatioByHeight = !_lockRatioByWidth;
            }
        }

        #endregion Region Filter Properties

        #region Ctor
        public Resize(int newWidth, int newHeight, bool keepAspectRatio)
        {
            _newHeight = newHeight;
            _newWidth = newWidth;
            _keepAspectRatio = keepAspectRatio;
        }
        public Resize() { }
        #endregion

        #region Private Methods
        /// <summary>
        /// Calculates the picture aspect ratio
        /// by dividing the width by the height
        /// </summary>
        /// <param name="width">image width</param>
        /// <param name="height">image height</param>
        /// <returns>aspect ratio</returns>
        private float CalcAspectRatio(int width, int height)
        {
            return (height == 0) ? 0 : (float)width / (float)height;
        }
        #endregion Private Methods

        #region Public Filter Methods
        /// <summary>
        /// Executes this filter on the input image and returns the result
        /// </summary>
        /// <param name="inputImage">input image</param>
        /// <returns>transformed image</returns>
        /// <example>
        /// <code>
        /// Image transformed;
        /// ResizeFilter resize = new ResizeFilter();
        /// resize.Width = 100;
        /// resize.Height = 70;
        /// transformed = resize.ExecuteFilter(myImg);
        /// </code>
        /// </example>
        public override void Apply(Bitmap b)
        {
            b = Convert(b);
            _b = b;
        }

        public override Bitmap Convert(Bitmap b)
        {
            _b = b;

            if (_keepAspectRatio)
            {
                _aspectRatio = CalcAspectRatio(b.Width, b.Height);
                if (_lockRatioByHeight)
                    _newWidth = (int)(_aspectRatio * Height);
                else
                    _newHeight = (int)(_newWidth / _aspectRatio);
            }
            Bitmap result = new Bitmap(_newWidth, _newHeight);
            Graphics g = Graphics.FromImage(result);
            g.InterpolationMode = _interpolationMode;
            g.DrawImage(b, 0, 0, _newWidth, _newHeight);
            return result;
        }
        #endregion

        protected override void FilterImplementation()
        {
            throw new NotImplementedException("Low level mode is not implemented");
        }
    }
}
